Imports Clo = Enhancements.Core.Logging
Imports Ere = Enhancements.Basic.RegularExpressions
Imports Exe = Enhancements.Basic.Expressions
Imports Gen = System.Collections.Generic
Imports Glo = System.Globalization
Imports Iou = System.IO
Imports Ref = System.Reflection
Imports Reg = System.Text.RegularExpressions
Imports Sys = System
Imports Tex = System.Text
Imports Xsd = System.Xml.Schema
Imports W3c = System.Xml

Namespace Enhancements.Basic.Expressions.Levels
    ''' <summary>Represents a token extracted from an expression that has a level delimiter.</summary>
    <Serializable(), DebuggerStepThrough()> _
    Public MustInherit Class Delimiter
        Inherits Exe.Token

        Friend Sub New(ByVal _expression As System.String, ByVal _expressionBeginIndex As Sys.Int32, ByVal _expressionEndIndex As Sys.Int32)
            MyBase.New(_expression, _expressionBeginIndex, _expressionEndIndex)
        End Sub

        Private Shared __DelimitersSorted As Gen.Dictionary(Of System.String, Sys.Type) = Nothing
        Private Shared Function __DelimitersSortedGet() As Gen.Dictionary(Of System.String, Sys.Type)
            If __DelimitersSorted.IsNull("__DelimitersSorted", False) Then
                Dim _delimitersSortedDictionary As Gen.SortedDictionary(Of System.String, Sys.Type) = New Gen.SortedDictionary(Of System.String, Sys.Type)()
                _delimitersSortedDictionary.Add(DelimiterBegin.Representation, GetType(DelimiterBegin))
                _delimitersSortedDictionary.Add(DelimiterEnd.Representation, GetType(DelimiterEnd))
                __DelimitersSorted = New Gen.Dictionary(Of System.String, Sys.Type)()
                For _counter As Sys.Int32 = _delimitersSortedDictionary.Count - 1 To 0 Step -1
                    __DelimitersSorted.Add(_delimitersSortedDictionary.ElementAt(_counter).Key, _delimitersSortedDictionary.ElementAt(_counter).Value)
                Next _counter
            End If

            Return __DelimitersSorted
        End Function

        Private Shared Function __Parse(ByVal _expression As System.String, ByVal _expressionBeginIndex As Sys.Int32) As Sys.Object
            Dim _returnValue As Sys.Object = Nothing
            Dim _delimiterBegin As DelimiterBegin = Nothing
            Dim _delimiterEnd As DelimiterEnd = Nothing
            For Each _delimiter As Sys.Type In __DelimitersSortedGet().Values.ToArray()
                If _delimiter.Is("_delimiter", GetType(DelimiterBegin), "GetType(DelimiterBegin)", False) AndAlso DelimiterBegin.TryParse(_expression, _expressionBeginIndex, _delimiterBegin).IsTrue("DelimiterBegin.TryParse(_expression, _expressionBeginIndex, _delimiterBegin)", False) Then
                    _returnValue = _delimiterBegin
                    Exit For
                Else
                    If _delimiter.Is("_delimiter", GetType(DelimiterEnd), "GetType(DelimiterEnd)", False) AndAlso DelimiterEnd.TryParse(_expression, _expressionBeginIndex, _delimiterEnd).IsTrue("DelimiterEnd.TryParse(_expression, _expressionBeginIndex, _delimiterEnd)", False) Then
                        _returnValue = _delimiterEnd
                        Exit For
                    End If
                End If
            Next _delimiter
            If Assert.IsNull(_returnValue, "_returnValue", False) Then
                _returnValue = DelimiterParseException.___Create(_expression, _expressionBeginIndex)
            End If

            Return _returnValue
        End Function

        ''' <summary>Parses an expression for a level delimiter starting by a begin index.</summary>
        ''' <param name="_expression">Expression to parse.</param>
        ''' <param name="_expressionBeginIndex">Expression begin index to use.</param>
        ''' <exception cref="DelimiterParseException">The operation did not produce a valid token.</exception>
        ''' <returns> </returns>
        Public Shared Function Parse(ByVal _expression As System.String, ByVal _expressionBeginIndex As Sys.Int32) As Delimiter
            Dim _returnValue As Sys.Object = __Parse(_expression, _expressionBeginIndex)
            If Assert.IsOfType(_returnValue, "_returnValue", GetType(DelimiterParseException), False) Then
                DelimiterParseException.___Throw(CType(_returnValue, DelimiterParseException))
            End If

            Return CType(_returnValue, Delimiter)
        End Function

        ''' <summary>Tries to parse an expression for a level delimiter starting by a begin index.</summary>
        ''' <param name="_expression">Expression to parse.</param>
        ''' <param name="_expressionBeginIndex">Expression begin index to use.</param>
        ''' <param name="_result">The result of the operation if possible. If not, null is returned.</param>
        ''' <returns> </returns>
        Public Shared Function TryParse(ByVal _expression As System.String, ByVal _expressionBeginIndex As Sys.Int32, ByRef _result As Delimiter) As System.Boolean
            Dim _returnValue As System.Boolean = False
            Dim _dummy As Sys.Object = __Parse(_expression, _expressionBeginIndex)
            If Assert.IsOfType(_dummy, "_dummy", GetType(DelimiterParseException), False) Then
                _result = Nothing
                _returnValue = False
            Else
                _result = CType(_dummy, Delimiter)
                _returnValue = True
            End If

            Return _returnValue
        End Function

        ''' <exception cref="IsNullException"> </exception>
        ''' <exception cref="IsListFilledNotException"> </exception>
        ''' <exception cref="CompilerExpressionLevelsDelimitersCountAreEqualNotException"> </exception>
        ''' <exception cref="CompilerExpressionLevelsDelimitersAreValidNotException"> </exception>
        Friend Shared Sub ___Assert(ByVal _tokensList As Gen.List(Of Token))
            _tokensList.IsListFilled("_tokensList", True)

            Dim _delimiterBeginTokensCount As Sys.Int32 = 0
            Dim _delimiterEndTokensCount As Sys.Int32 = 0
            For _counter As Sys.Int32 = 0 To _tokensList.Count - 1
                If _tokensList(_counter).IsOfType("_tokensList(_counter)", GetType(DelimiterBegin), False) Then
                    _delimiterBeginTokensCount += 1
                End If
                If _tokensList(_counter).IsOfType("_tokensList(_counter)", GetType(DelimiterEnd), False) Then
                    _delimiterEndTokensCount += 1
                End If
            Next _counter
            If _delimiterBeginTokensCount.IsInRangeNot("_delimiterBeginTokensCount", _delimiterEndTokensCount, _delimiterEndTokensCount, False) Then
                CompilerExpressionLevelsDelimitersCountAreEqualNotException.___Throw(_tokensList(0).Expression, _delimiterBeginTokensCount, _delimiterEndTokensCount)
            End If
            Dim _currentLevel As System.Int32 = 0
            For _counter As Sys.Int32 = 0 To _tokensList.Count - 1
                If _tokensList(_counter).IsOfType("_tokensList(_counter)", GetType(DelimiterBegin), False) Then
                    _currentLevel += 1
                End If
                If _tokensList(_counter).IsOfType("_tokensList(_counter)", GetType(DelimiterEnd), False) Then
                    _currentLevel -= 1
                End If
                If _currentLevel.IsInRangeNot("_currentLevel", 0, Sys.Int32.MaxValue, False) Then
                    Exit For
                End If
            Next _counter
            If _currentLevel.IsInRangeNot("_currentLevel", 0, 0, False) Then
                CompilerExpressionLevelsDelimitersAreValidNotException.___Throw(_tokensList(0).Expression)
            End If
        End Sub

        ''' <exception cref="IsNullException"> </exception>
        ''' <exception cref="IsListFilledNotException"> </exception>
        Friend Shared Function ___FindDeepestLevelDepth(ByVal _tokensList As Gen.List(Of Token)) As System.Int32
            _tokensList.IsListFilled("_tokensList", True)

            Dim _currentLevelDepth As Sys.Int32 = 0
            Dim _returnValue As Sys.Int32 = 0
            For _counter As Sys.Int32 = 0 To _tokensList.Count - 1
                If _tokensList(_counter).IsOfType("_tokensList(_counter)", GetType(DelimiterBegin), False) Then
                    _currentLevelDepth += 1
                    _returnValue = Sys.Math.Max(_currentLevelDepth, _returnValue)
                End If
                If _tokensList(_counter).IsOfType("_tokensList(_counter)", GetType(DelimiterEnd), False) Then
                    _currentLevelDepth -= 1
                End If
            Next _counter

            Return _returnValue
        End Function

        ''' <exception cref="IsNullException"> </exception>
        ''' <exception cref="IsListFilledNotException"> </exception>
        ''' <exception cref="IsInRangeNotException"> </exception>
        Friend Shared Sub ___FindDeepestLevelBeginAndEndTokensIndexes(ByVal _tokensList As Gen.List(Of Token), ByRef _beginAndEndTokensExist As System.Boolean, ByRef _beginTokenIndex As Sys.Int32, ByRef _endTokenIndex As Sys.Int32)
            _tokensList.IsListFilled("_tokensList", True)
            _tokensList.Count.IsInRange("_tokensList.Count", 1, Sys.Int32.MaxValue, True)

            Dim _deepestLevelDepth As Sys.Int32 = ___FindDeepestLevelDepth(_tokensList)
            If _deepestLevelDepth.IsInRange("_deepestLevelDepth", 0, 0, False) Then
                _beginAndEndTokensExist = False
                _beginTokenIndex = 0
                _endTokenIndex = _tokensList.Count - 1
            Else
                _beginAndEndTokensExist = True
                Dim _currentLevelDepth As Sys.Int32 = 0
                For _counter As Sys.Int32 = 0 To _tokensList.Count - 1
                    If _tokensList(_counter).IsOfType("_tokensList(_counter)", GetType(DelimiterBegin), False) Then
                        _currentLevelDepth += 1
                        If _currentLevelDepth.IsInRange("_currentLevelDepth", _deepestLevelDepth, _deepestLevelDepth, False) Then
                            _beginTokenIndex = _counter
                        End If
                    End If
                    If _tokensList(_counter).IsOfType("_tokensList(_counter)", GetType(DelimiterEnd), False) Then
                        _currentLevelDepth -= 1
                        If _beginTokenIndex.IsInRangeNot("_beginTokenIndex", -1, -1, False) Then
                            _endTokenIndex = _counter
                            Exit For
                        End If
                    End If
                Next _counter
            End If
        End Sub

    End Class
End Namespace
